<?php

namespace App\Http\Repositories\Daos;

use Illuminate\Support\Facades\DB;

/**
 * Created by PhpStorm.
 * User: lishengbin
 * Date: 2019/9/12
 * Time: 16:59
 */
class BaseDao
{

    protected $model;

    public function __construct($model)
    {
        $this->model = $model;
    }

    /**
     * 查询一行 基于主键
     * @param $id
     * @param array $select
     * @return mixed
     */
    public function findOne($id, $select = [])
    {
        $filterMap = $this->model->newQuery();
        if(!empty($select)) {
            $filterMap->select($select);
        }
        return $filterMap->find($id);
    }

    /**
     * 查询多行 基于键值
     * @param $ids
     * @param string $key
     * @param array $select
     * @return mixed
     */
    public function findByIds($ids, $key = 'id', $select = [])
    {
        $filterMap = $this->model->newQuery();
        if(!empty($select)) {
            $filterMap->select($select);
        }
        return $filterMap->whereIn($key, $ids)->get();
    }

    /**
     * @param $ids id数组
     * @param string $key id key值
     * @param string $byKey 指定返回集合的键
     * @param array $select 获取指定字段
     * @return mixed
     */
    public function findByIdsKeyByKeys($ids, $key = 'id', $byKey = 'id', $select = [])
    {
        $map = $this->model;
        if(!empty($select)) {
            if(!array_key_exists($key, $select)){
                $select[] = $key;
            }
            $map = $map->select($select);
        }
        return $map->whereIn($key, $ids)->get()->keyBy($byKey);
    }

    /**
     * 获取表所有行
     * @param int $limit
     * @param string $key
     * @param string $sort
     * @return mixed
     */
    public function findAll($limit = 10, $key = 'created_at', $sort = 'DESC')
    {
        $limit = $limit > 0 ? $limit : 10;
        return $this->model->orderBy($key,$sort)->skip(0)->take($limit)->get();
    }

    /**
     * 基于单列 查询语句 查询
     * @param $key
     * @param $symbol
     * @param $val
     * @return mixed
     */
    public function findByKey($key, $symbol, $val)
    {
        return $this->model->where($key, $symbol, $val)->get();
    }

    /**
     * 是否存在
     * @param $where
     * @return mixed
     */
    public function exists($where)
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        return $filterMap->exists();
    }

    /**
     * 传入查询条件 取一行
     * @param $where
     * @param $select
     * @return mixed
     */
    public function getOne($where, $select = [])
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if(!empty($select)) {
            $filterMap->select($select);
        }
        return $filterMap->first();
    }

    /**
     * 传入查询条件 取一行 的某列
     * @param $where
     * @param $valField
     * @param array $order
     * @return mixed
     */
    public function getOneField($where, $valField, $order = [])
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                $filterMap->where($key, $record['symbol'], $record['val']);
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if (!empty($order)) {
            foreach ($order as $key => $sort) {
                $filterMap->orderBy($key, $sort);
            }
        }
        return $filterMap->value($valField);
    }

    /**
     * 获取列表 最后 用指定key作为键
     * @param $where
     * @param string $byKey     结果数组键名
     * @param array $select
     * @param string[] $order
     * @return mixed
     */
    public function getList($where, $byKey = 'id', $select = [], $order = [])
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if(!empty($select)) {
            if(!array_key_exists($byKey, $select)){
                $select[] = $byKey;
            }
            $filterMap->select($select);
        }
        if (!empty($order)) {
            foreach ($order as $key => $sort) {
                $filterMap->orderBy($key, $sort);
            }
        }
        return $filterMap->get()->keyBy($byKey);
    }

    /**
     * 分页式获取列表 无需count
     * @param $where
     * @param array $select
     * @param int $page
     * @param int $size
     * @param array $order
     * @return mixed
     */
    public function getListPage($where, $select = [], $page = 1, $size = 10, $order = [])
    {
        $offset = ($page - 1) * $size;
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] == 'in') {
                    $filterMap->whereIn($key, $record['val']);
                } elseif ($record['symbol'] == 'between') {
                    $filterMap->whereBetween($key, $record['val']);
                } else {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if(!empty($select)) {
            $filterMap->select($select);
        }
        if (!empty($order)) {
            foreach ($order as $key => $sort) {
                $filterMap->orderBy($key, $sort);
            }
        }

        return $filterMap->skip($offset)->take($size)->get();
    }

    /**
     * 基于条件获取列表
     * @param $where
     * @param array $select
     * @param string[] $order
     * @return mixed
     */
    public function getListNoKey($where, $select = [], $order = [])
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if(!empty($select)) {
            $filterMap->select($select);
        }
        if (!empty($order)) {
            foreach ($order as $key => $sort) {
                $filterMap->orderBy($key, $sort);
            }
        }
        return $filterMap->get();
    }

    /**
     * 保存新行
     * @param $data
     * @return mixed
     */
    public function save($data)
    {
        return $this->model->create($data);
    }

    /**
     * 基于主键 更新
     * @param $id
     * @param $data
     * @param string $key
     * @return mixed
     */
    public function update($id, $data, $key = 'id')
    {
        return $this->model->where($key, $id)->update($data);
    }

    /**
     * 基于查询条件 更新
     * @param $where
     * @param $data
     * @return mixed
     */
    public function updates($where, $data)
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        return $filterMap->update($data);
    }

    /**
     * 自增
     * @param $field
     * @param int $value
     * @param array $where
     * @param array $update
     * @return mixed
     */
    public function increment($field, $value = 1, $where = [], $update = [])
    {
        $filterMap = $this->model->newQuery();
        if (!empty($where)) {
            foreach ($where as $key => $record) {
                if (isset($record['symbol']) && isset($record['val'])) {
                    if ($record['symbol'] != 'in') {
                        $filterMap->where($key, $record['symbol'], $record['val']);
                    } else {
                        $filterMap->whereIn($key, $record['val']);
                    }
                } else {
                    $filterMap->where($key, '=', $record);
                }
            }
        }
        return $filterMap->increment($field, $value, $update);
    }

    /**
     * 自减
     * @param $field
     * @param $value
     * @param array $where
     * @param array $update
     * @return mixed
     */
    public function decrement($field, $value, $where = [], $update = [])
    {
        $filterMap = $this->model->newQuery();
        if (!empty($where)) {
            foreach ($where as $key => $record) {
                if (isset($record['symbol']) && isset($record['val'])) {
                    if ($record['symbol'] != 'in') {
                        $filterMap->where($key, $record['symbol'], $record['val']);
                    } else {
                        $filterMap->whereIn($key, $record['val']);
                    }
                } else {
                    $filterMap->where($key, '=', $record);
                }
            }
        }
        return $filterMap->decrement($field, $value, $update);
    }

    /**
     * 计数
     * @param $where
     * @return mixed
     */
    public function count($where)
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        return $filterMap->count();
    }

    /**
     * 汇总
     * @param $where
     * @param $field
     * @return mixed
     */
    public function sum($where, $field)
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        return $filterMap->sum($field);
    }

    /**
     * 基于键删除
     * @param $id
     * @param string $key
     * @return mixed
     */
    public function delete($id, $key = 'id')
    {
        $filterMap = $this->model->newQuery();
        return $filterMap->where($key, '=', $id)->delete();
    }

    /**
     * 基于键数组删除
     * @param $ids
     * @param string $key
     * @return mixed
     */
    public function deletes($ids, $key = 'id')
    {
        $filterMap = $this->model->newQuery();
        return $filterMap->whereIn($key, $ids)->delete();
    }

    /**
     * 基于条件删除
     * @param $where
     * @return mixed
     */
    public function deleteByWhere($where)
    {
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        return $filterMap->delete();
    }

    /**
     * 根据条件 多个字段增加值
     * @param $where
     * @param array $increments
     * @return bool
     */
    public function manyIncrementOnce($where, $increments = [])
    {
        if(empty($where) || empty($increments)) {
            return false;
        }
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        $aUpdateData = [];
        foreach ($increments as $incKey => $incValue) {
            $aUpdateData[$incKey] = $incValue > 0 ? DB::raw($incKey. ' + ' . $incValue) : DB::raw($incKey. ' - ' . abs($incValue));
        }
        return $filterMap->update($aUpdateData);
    }

    /**
     * 有 count 的获取列表 及总数
     * @param $filterMap
     * @param int $offset
     * @param int $size
     * @param string[] $order
     * @return array
     */
    public function page($filterMap, $offset = 0, $size = 10, $order = [])
    {
        $result = ['totalCount'=>0, 'results'=>[]];

        $offset = intval($offset);

        $size = intval($size) ? intval($size) : 10;

        $result['totalCount'] = $filterMap->count();

        if ($result['totalCount'] > 0) {
            if ((bool)$order) {
                foreach ($order as $key => $sort) {
                    $filterMap->orderBy($key, $sort);
                }
            }
            $result['results'] = $filterMap->skip($offset)->take($size)->get()->toArray();
        }

        return $result;
    }

    /**
     * 获取字段值列表 $keyField 有值表示 作为key值
     * @param $where
     * @param $valField
     * @param string $keyField
     * @param $order
     * @return mixed
     */
    public function pluck($where = [], $valField, $keyField='', $order = [])
    {
        if(empty($valField)) {
            return false;
        }
        $filterMap = $this->model->newQuery();
        foreach ($where as $key => $record) {
            if (isset($record['symbol']) && isset($record['val'])) {
                if ($record['symbol'] != 'in') {
                    $filterMap->where($key, $record['symbol'], $record['val']);
                } else {
                    $filterMap->whereIn($key, $record['val']);
                }
            } else {
                $filterMap->where($key, '=', $record);
            }
        }
        if (!empty($order)) {
            foreach ($order as $key => $sort) {
                $filterMap->orderBy($key, $sort);
            }
        }
        if($keyField) {
            return $filterMap->pluck($valField, $keyField);
        } else {
            return $filterMap->pluck($valField);
        }
    }

    /**
     * 返回当前 model
     * @return mixed
     */
    public function getModel()
    {
        return $this->model;
    }

    public function toSql()
    {
        $filterMap = $this->model->newQuery();
        return $filterMap->getQueryLog();
    }




}
